//-------------------------------------------------------------------
//	Copyright (c) 2010-2012 Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#ifndef _UX_RENDER_TECHNIQUE_MANAGER_H
#define _UX_RENDER_TECHNIQUE_MANAGER_H

#include "IRenderTechnique.h"
#include "CDefaultRenderTech.h"
#include "CConfiguredRenderTech.h"
#include "../Utils/CViewport.h"

namespace Engine
{
namespace RenderUtils
{

	typedef bool (CALLBACK *PCreateRenderTechProc_t)(IRenderTechnique *&, void *);
	typedef bool (CALLBACK *PCreateConfiguredRTProc_t)(CConfiguredRenderTech *&, void *);
	



	//
	// Render Technique Event Listener intarface
	//

	class IRTEventListener
	{
	public:
		virtual void OnTechniqueChanged(IRenderTechnique *) = 0;
	};




	//
	// Render Technique Manager
	//

	class _EXPORT_ CRenderTechniqueManager : public CEngBaseObject
	{
		friend class Engine::CoreSystems::CRender;
		friend class Engine::CoreSystems::CRenderThread;
		
	protected:

		struct TRenTechInfo
		{
			string				sAddress;
			e_technique::type	eType;
			///
			TRenTechInfo(): eType(e_technique::UNKNOWN) {}
		};
		friend _CREATE_META_OBJECT_FD( TRenTechInfo );


		struct TCustomRenTechInfo
		{
			PCreateRenderTechProc_t	pProc;
			void			*		pParam;
			e_technique::type		eType;
			///
			TCustomRenTechInfo(): pProc(nullfunc), eType(e_technique::UNKNOWN), pParam(nullptr) {}
			TCustomRenTechInfo(PCreateRenderTechProc_t proc, void *param, e_technique::type type):
				pProc(proc), eType(type), pParam(param) {}
		};

		typedef array< TRenTechInfo >												rt_info_array_t;
		typedef array< IRenderTechnique *, TFastCopyStrategy< IRenderTechnique *> >	rentech_array_t;
		typedef array< TCustomRenTechInfo >											custom_rt_array_t;
		typedef array< IRTEventListener *, TFastCopyStrategy< IRTEventListener *> >	rt_eventlist_array_t;


	protected:
		rt_eventlist_array_t		_aEventListeners;
		rentech_array_t				_aRenTechniques;
		rt_info_array_t				_aRenTechInfos;
		custom_rt_array_t			_aCustomRTInfos;
		PCreateConfiguredRTProc_t	_pCRTConstructor;
		CDefaultRenderTech			_cDefaultRT;
		CRTPassManager				_cPassManager;
		void					*	_pCRTParameter;
		IRenderTechnique		*	_pCurRenderTech;


	protected:
		CRenderTechniqueManager();
		~CRenderTechniqueManager();
		
		bool Init();
		void Destroy();
		void _InitMetaData();
		void _SetTechnique(IRenderTechnique *);

		static bool CALLBACK _s_CreateConfiguredRT(CConfiguredRenderTech *&, void *);

	public:
		bool CreateTechnique(IRenderTechnique *&pTech, e_technique::type eType);
		void GetNearestType(e_technique::type eRequiredType, e_technique::type &eResult);

		bool RegisterTechnique(PCreateRenderTechProc_t pProc, e_technique::type eType, void *pParam = nullptr);
		bool UnRegisterTechnique(e_technique::type eType);
		void SetConfiguredRTConstructor(PCreateConfiguredRTProc_t pProc = nullfunc, void *pParam = nullptr);

		void AddRenderTechnique(IRenderTechnique *);
		bool RemoveRenderTechnique(IRenderTechnique *);

		void AddEventListener(IRTEventListener *);
		bool RemoveEventListener(IRTEventListener *);


		CRTPassManager *	GetPassManager()	{ return &_cPassManager; }


		// CEngBaseObject //
		virtual void Release();
	};

//-------------------------------------------------------------------

}	// RenderUtils
}	// Engine

#endif	// _UX_RENDER_TECHNIQUE_MANAGER_H